[GitHub Actions] モノリポ環境の node_modules をキャッシュする際にはパスの指定に気をつけよう
こんにちは、CX 事業本部 Delivery 部の若槻です。
npm workspaces を使用すると、モノリポ環境の依存関係(node_modules
)を容易に管理可能になります。
今回は、GitHub Actions でモノリポ環境の node_modules
をキャッシュする際のパス指定でハマった事象について紹介します。
最初に結論
GitHub Actions のワークフローで actions/cache を使って node_modules
をキャッシュする際には、path
に **/node_modules
と指定する必要がありました。
on: pull_request: jobs: integrate: runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v3 - name: Cache Dependency uses: actions/cache@v3 id: cache_dependency env: cache-name: cache-dependency with: path: "**/node_modules" # 正しいパス指定 key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}
事象
当初、ワークフローでの actions/cache でのパスを以下のように node_modules
と指定していました。
on: pull_request: jobs: integrate: runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v3 - name: Cache Dependency uses: actions/cache@v3 id: cache_dependency env: cache-name: cache-dependency with: path: node_modules # 誤ったパス指定 key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }} - name: Install Dependency if: ${{ steps.cache_dependency.outputs.cache-hit != 'true' }} run: npm ci - name: Lint & Format run: | npm run lint npm run format - name: tsc run: npm run type-check-all - name: Cdk Synth run: npm run synth:dev - name: Unit Test run: npm run test-unit -- run
上記のワークフローは 1 回目の実行では正常にパスしました。
しかし 2 回目以降のワークフロー実行では、tsc による型チェックで Cannot find module '@aws-sdk/lib-dynamodb' or its corresponding type declarations.
のようなエラーが発生するようになりました。
原因
事象が発生したワークフローではルートの node_modules
のみをキャッシュ対象としていました。しかし npm workspaces 環境では次のようにルート以外の各ワークスペースのパスにも node_modules
が作成されて管理されます。
$ find . -name "node_modules" -type d -not -path "./node_modules/*" ./node_modules ./packages/server/node_modules ./packages/e2e/node_modules
そのため、各ワークスペースのパスの node_modules
がキャッシュおよび復元されない場合には、ルートの node_modules
には存在しないモジュールのインポートが試行された際に前述のようなエラーが発生します。
対処
よって、冒頭で示した通り、actions/cache でのパスを以下のように **/node_modules
と指定することで、ルートに加えて各ワークスペースの node_modules
がキャッシュされるようになります。
on: pull_request: jobs: integrate: runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v3 - name: Cache Dependency uses: actions/cache@v3 id: cache_dependency env: cache-name: cache-dependency with: path: "**/node_modules" # 正しいパス指定 key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }} - name: Install Dependency if: ${{ steps.cache_dependency.outputs.cache-hit != 'true' }} run: npm ci - name: Lint & Format run: | npm run lint npm run format - name: tsc run: npm run type-check-all - name: Cdk Synth run: npm run synth:dev - name: Unit Test run: npm run test-unit -- run
上記対処後は、キャッシュが利用された場合でも、tsc 含めた各ステップが正常に完了するようになりました。
おわりに
GitHub Actions でモノリポ環境の node_modules
をキャッシュする際のパス指定でハマった事象についてご紹介しました。
キャッシュが使われる(= package-lock.json
に変更が無い)ワークフロー実行時に初めて今回の事象が発生するようになったため、若干原因究明にまごつきましたが、結論として単純な考慮忘れによるものでした。社内で助け舟を出してくださったたにもんさんには感謝。
以上